
#include "usart1.h"


OS_EVENT * USART1_Recv_Sem;

typedef struct _st_USART1_RX {
	UINT8 qbuf[128];
	UINT32 qlen;
	
	UINT8 buf[128];
	UINT32 len;
	UINT32 GetFlag;
}st_USART1_RX;

st_USART1_RX  USART1_RX;

enum{
	FLAG_RX_FULL		= (1<<0),
	FLAG_RX_END			= (1<<1),
	FLAG_RX_OVERLAP 	= (1<<2),
	FLAG_RX_IDLE		= 0,
};



//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
void usart1_init(u32 bound){
  //GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1，GPIOA时钟

	//USART1_TX   GPIOA.9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9

	//USART1_RX	  GPIOA.10初始化
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

	//Usart1 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

	//USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	
	//USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
	USART_InitStructure.USART_Mode = USART_Mode_Tx;//发模式
	
	USART_Init(USART1, &USART_InitStructure); //初始化串口1
	//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);


	USART_Cmd(USART1, ENABLE);                    //使能串口1 


}

void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res;
#if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真，则需要支持OS.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据		
		if (USART1_RX.qlen < sizeof(USART1_RX.qbuf))
		{
			USART1_RX.qbuf[USART1_RX.qlen] = Res;	
			USART1_RX.qlen++;
		}	  
		else
		{
			USART1_RX.GetFlag |= FLAG_RX_FULL;
		}		
					 
   } 
	
	if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
    {
        USART_ReceiveData(USART1);  
        USART_ClearITPendingBit(USART1,USART_IT_IDLE);
		if (USART1_RX.GetFlag & FLAG_RX_END)
		{
			USART1_RX.GetFlag |= FLAG_RX_OVERLAP;
		}	
		else
		{
			USART1_RX.GetFlag |= FLAG_RX_END;
		}	
		
	
		if (USART1_RX.qlen > 0)
		{	

			memcpy(USART1_RX.buf, USART1_RX.qbuf, USART1_RX.qlen);
			
			USART1_RX.len = USART1_RX.qlen;
			USART1_RX.qlen = 0;
			
			OSSemPost(USART1_Recv_Sem);
		}
	}

#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真，则需要支持OS.
	OSIntExit();  											 
#endif
} 


/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
** 函数名称: USART1_Read
** 功能描述: 串口1接收数据
** 参数描述：无
** return	 : 返回1表示接收到数据，0表示没有接收到数据
** 作  　者: msl
** 日　  期: 2015年12月18日
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
INT32 USART1_Read(UINT8 *BUF, UINT32 len, UINT32 timeout)
{
	INT32 ret;
    UINT8 err = 0;	
	UINT32 tlen = 0;
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
		OS_CPU_SR  cpu_sr = 0u;
#endif		
	OSSemPend(USART1_Recv_Sem, timeout, &err); 
	if (err == OS_ERR_NONE)
	{
		OS_ENTER_CRITICAL();
		if (len < USART1_RX.len)
		{
			tlen = len;
		}	
		else
		{
			tlen = USART1_RX.len;
		}	
		memcpy(BUF,USART1_RX.buf, tlen);
		USART1_RX.GetFlag &= (~(FLAG_RX_END|FLAG_RX_OVERLAP));		
		ret = tlen;
		USART1_RX.len = 0;
		OS_EXIT_CRITICAL();	
	}	
	else
	{
		ret = -1;
	}	
	return ret;
}




INT32 USART1_Read_NoBlock(UINT8 *BUF, UINT32 len)
{
	INT32 ret;
	UINT32 tlen = 0;
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
		OS_CPU_SR  cpu_sr = 0u;
#endif		

	if (OSSemAccept(USART1_Recv_Sem) > 0)
	{
		OS_ENTER_CRITICAL();
		if (len < USART1_RX.len)
		{
			tlen = len;
		}	
		else
		{
			tlen = USART1_RX.len;
		}	
		memcpy(BUF,USART1_RX.buf, tlen);
		USART1_RX.GetFlag &= (~(FLAG_RX_END|FLAG_RX_OVERLAP));		
		ret = tlen;
		USART1_RX.len = 0;
		OS_EXIT_CRITICAL();	
	}	
	else
	{
		ret = -1;
	}	
	return ret;
}





void USART1_CLEAR_RX(void)
{
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
		OS_CPU_SR  cpu_sr = 0u;
#endif		
	OS_ENTER_CRITICAL();
	USART1_RX.GetFlag = FLAG_RX_IDLE;	
	USART1_RX.len = 0;
	USART1_RX.qlen = 0;
	USART1_Recv_Sem->OSEventCnt = 0;
	OS_EXIT_CRITICAL();		
}	


void USART1_Create_Sem(void)
{	
#if OS_CRITICAL_METHOD == 3u
    OS_CPU_SR cpu_sr=0u;
#endif
    OS_ENTER_CRITICAL();  //进入临界区(关闭中断)   
	USART1_Recv_Sem = OSSemCreate(0); 
    OS_EXIT_CRITICAL();  //退出临界区(开中断)
}

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
** 函数名称: uart1_putc
** 功能描述: 串口1发送一个字节
** 参数描述：发送的数据
** return	 : 无
** 作  　者: msl
** 日　  期: 2015年12月18日
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
void uart1_putc(u8 c)
{
  u16 wCtr = 1; 
  
  USART_SendData(USART1,c);
  // Loop until the end of transmit 
  while((USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) && (wCtr != 0))
  {
    wCtr++;
  }
}

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
** 函数名称: uart1_puthex
** 功能描述: 串口1发送一个16进制数
** 参数描述：发送的数据
** return	 : 无
** 作  　者: msl
** 日　  期: 2015年12月18日
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
void uart1_puthex(u8 c)
{
  u8 iTemp;

  iTemp = c >> 4;
  if(iTemp <= 9){
    uart1_putc(iTemp+0x30);
  }else if((iTemp >= 0x0a) && (iTemp <= 0x0f)){
    uart1_putc(iTemp+0x41-0x0a);
  }	
  iTemp = c & 0x0f;
  if(iTemp <= 9){
    uart1_putc(iTemp+0x30);
  }else if((iTemp >= 0x0a) && (iTemp <= 0x0f)){
    uart1_putc(iTemp+0x41-0x0a);
  }
}

